5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 3.1.0
47 require_once 'PHPUnit/Util/Filter.php';
49 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
56 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
57 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
58 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
59 * @version Release: 3.3.17
60 * @link http://www.phpunit.de/
61 * @since Class available since Release 3.1.0
63 class PHPUnit_Util_Class
65 protected static $buffer = array();
66 protected static $fileClassMap = array();
67 protected static $fileFunctionMap = array();
70 * Starts the collection of loaded classes.
73 public static function collectStart()
75 self::$buffer = get_declared_classes();
79 * Stops the collection of loaded classes and
80 * returns the names of the loaded classes.
84 public static function collectEnd()
87 array_diff(get_declared_classes(), self::$buffer)
92 * Stops the collection of loaded classes and
93 * returns the names of the files that declare the loaded classes.
97 public static function collectEndAsFiles()
99 $result = self::collectEnd();
100 $count = count($result);
102 for ($i = 0; $i < $count; $i++) {
103 $class = new ReflectionClass($result[$i]);
105 if ($class->isUserDefined()) {
106 $file = $class->getFileName();
108 if (file_exists($file)) {
120 * Returns the names of the classes declared in a sourcefile.
122 * @param string $filename
123 * @param string $commonPath
124 * @param boolean $clearCache
127 public static function getClassesInFile($filename, $commonPath = '', $clearCache = FALSE)
129 if ($commonPath != '') {
130 $filename = str_replace($commonPath, '', $filename);
134 self::$fileClassMap = array();
137 if (empty(self::$fileClassMap)) {
138 $classes = array_merge(get_declared_classes(), get_declared_interfaces());
140 foreach ($classes as $className) {
141 $class = new ReflectionClass($className);
143 if ($class->isUserDefined()) {
144 $file = $class->getFileName();
146 if ($commonPath != '') {
147 $file = str_replace($commonPath, '', $file);
150 if (!isset(self::$fileClassMap[$file])) {
151 self::$fileClassMap[$file] = array($class);
153 self::$fileClassMap[$file][] = $class;
159 return isset(self::$fileClassMap[$filename]) ? self::$fileClassMap[$filename] : array();
163 * Returns the names of the classes declared in a sourcefile.
165 * @param string $filename
166 * @param string $commonPath
167 * @param boolean $clearCache
169 * @since Method available since Release 3.2.0
170 * @todo Find a better place for this method.
172 public static function getFunctionsInFile($filename, $commonPath = '', $clearCache = FALSE)
174 if ($commonPath != '') {
175 $filename = str_replace($commonPath, '', $filename);
179 self::$fileFunctionMap = array();
182 if (empty(self::$fileFunctionMap)) {
183 $functions = get_defined_functions();
185 foreach ($functions['user'] as $functionName) {
186 $function = new ReflectionFunction($functionName);
188 $file = $function->getFileName();
190 if ($commonPath != '') {
191 $file = str_replace($commonPath, '', $file);
194 if (!isset(self::$fileFunctionMap[$file])) {
195 self::$fileFunctionMap[$file] = array($function);
197 self::$fileFunctionMap[$file][] = $function;
202 return isset(self::$fileFunctionMap[$filename]) ? self::$fileFunctionMap[$filename] : array();
206 * Returns the class hierarchy for a given class.
208 * @param string $className
209 * @param boolean $asReflectionObjects
212 public static function getHierarchy($className, $asReflectionObjects = FALSE)
214 if ($asReflectionObjects) {
215 $classes = array(new ReflectionClass($className));
217 $classes = array($className);
223 if ($asReflectionObjects) {
224 $class = new ReflectionClass($classes[count($classes)-1]->getName());
226 $class = new ReflectionClass($classes[count($classes)-1]);
229 $parent = $class->getParentClass();
231 if ($parent !== FALSE) {
232 if ($asReflectionObjects) {
233 $classes[] = $parent;
235 $classes[] = $parent->getName();
246 * Returns the signature of a function.
248 * @param ReflectionFunction $function
250 * @since Method available since Release 3.3.2
251 * @todo Find a better place for this method.
253 public static function getFunctionSignature(ReflectionFunction $function)
255 if ($function->returnsReference()) {
265 $function->getName(),
266 self::getMethodParameters($function)
271 * Returns the signature of a method.
273 * @param ReflectionMethod $method
275 * @since Method available since Release 3.2.0
277 public static function getMethodSignature(ReflectionMethod $method)
279 if ($method->isPrivate()) {
280 $modifier = 'private';
283 else if ($method->isProtected()) {
284 $modifier = 'protected';
288 $modifier = 'public';
291 if ($method->isStatic()) {
292 $modifier .= ' static';
295 if ($method->returnsReference()) {
302 '%s function %s%s(%s)',
307 self::getMethodParameters($method)
312 * Returns the parameters of a function or method.
314 * @param ReflectionFunction|ReflectionMethod $method
316 * @since Method available since Release 3.2.0
318 public static function getMethodParameters($method)
320 $parameters = array();
322 foreach ($method->getParameters() as $i => $parameter) {
323 $name = '$' . $parameter->getName();
331 if ($parameter->isArray()) {
332 $typeHint = 'array ';
335 $class = $parameter->getClass();
338 catch (ReflectionException $e) {
343 $typeHint = $class->getName() . ' ';
349 if ($parameter->isDefaultValueAvailable()) {
350 $value = $parameter->getDefaultValue();
351 $default = ' = ' . var_export($value, TRUE);
354 else if ($parameter->isOptional()) {
355 $default = ' = null';
360 if ($parameter->isPassedByReference()) {
364 $parameters[] = $typeHint . $ref . $name . $default;
367 return join(', ', $parameters);
371 * Returns the sourcecode of a user-defined class.
373 * @param string $className
374 * @param string $methodName
377 public static function getMethodSource($className, $methodName)
379 if ($className != 'global') {
380 $function = new ReflectionMethod($className, $methodName);
382 $function = new ReflectionFunction($methodName);
385 $filename = $function->getFileName();
387 if (file_exists($filename)) {
388 $file = file($filename);
390 $start = $function->getStartLine() - 1;
391 $end = $function->getEndLine() - 1;
393 for ($line = $start; $line <= $end; $line++) {
394 $result .= $file[$line];
404 * Returns the package information of a user-defined class.
406 * @param string $className
409 public static function getPackageInformation($className)
419 if (strpos($className, ':') !== FALSE) {
420 $result['namespace'] = self::arrayToName(
421 explode('\\', $className), '\\'
425 $class = new ReflectionClass($className);
426 $docComment = $class->getDocComment();
428 if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
429 $result['category'] = $matches[1];
432 if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
433 $result['package'] = $matches[1];
434 $result['fullPackage'] = $matches[1];
437 if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
438 $result['subpackage'] = $matches[1];
439 $result['fullPackage'] .= '.' . $matches[1];
442 if (empty($result['fullPackage'])) {
443 $result['fullPackage'] = self::arrayToName(
444 explode('_', str_replace('\\', '_', $className)), '.'
452 * Returns the package information of a user-defined class.
454 * @param array $parts
455 * @param string $join
457 * @since Method available since Release 3.2.12
459 protected static function arrayToName(array $parts, $join)
463 if (count($parts) > 1) {
466 $result = join($join, $parts);